package com.zktr.utils;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import com.zktr.exception.JDBCException;


/**
 * 
 * @author 
 * @param <T>
 *
 */
public class CRUDDAO<T> {
	Connection con ;
	ResultSet rt;
	Statement st;
	PreparedStatement pt; 
	Class<T> c;
	public CRUDDAO(){
		
	}
	public CRUDDAO(Class<T> c){
		this.c=c;
	}
	public List<T>  select(String sql,Object ...obj){
		List<T> list=new ArrayList<>();
		try {
			con= BaseDAO.getConnections();
			if(con!=null){
				pt= con.prepareStatement(sql);
				bind(obj);
				 rt= pt.executeQuery();
				 while(rt.next()){
					 list.add(tobean());
				 }
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			BaseDAO.closeAll(con, st, rt);
		}
		return list;
	}
	/**
	 * 查询：
	 * @return
	 */
	public Map<Integer, List<T>>  selectAll(Map<String,Object []> map){
		Integer index=0;
		Map<Integer,List<T>> resultMap=new LinkedHashMap<>();
		List<T> list=new ArrayList<>();
		try {
			con= BaseDAO.getConnections();
			if(con!=null){
				Set<Entry<String, Object[]>> entrySet = map.entrySet();
				for (Entry<String, Object[]> entry : entrySet) {
				//	Object[] value = entry.getValue();
					pt=con.prepareStatement(entry.getKey());
					this.bind(entry.getValue());
					rt=pt.executeQuery();
					while(rt.next()){
						list.add(tobean());
					}
					
				}
				resultMap.put(index++, list);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			BaseDAO.closeAll(con, st, rt);
		}
		return resultMap;
	}
	/**
	 *分页查询
	 */
	public int selectCount(String sql){
		try {
			con= BaseDAO.getConnections();
			if(con!=null){
					pt=con.prepareStatement(sql);
					rt=pt.executeQuery();
					if(rt.next()){
						return rt.getInt(1);
					}
				}
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			BaseDAO.closeAll(con, pt, rt);
		}
		return 0;
	}
	
	public int selectCount(String sql,Object...obj){
		try {
			con= BaseDAO.getConnections();
			if(con!=null){
					pt=con.prepareStatement(sql);
					this.bind(obj);
					rt=pt.executeQuery();
					if(rt.next()){
						return rt.getInt(1);
					}
				}
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			BaseDAO.closeAll(con, pt, rt);
		}
		return 0;
	}
	/**
	 *  修改
	 */
	public int [] updateAll(Map<String, Object[]> map) {
		int error=0;
		int index=0;
		int [] row=new int[map.size()];
		try {
			con=BaseDAO.getConnections();
			if(con!=null){
				Set<Entry<String, Object[]>> entrySet = map.entrySet();
				//鍙栨秷MySQL鐨勮嚜鍔ㄦ彁浜ゅ姛鑳�
				con.setAutoCommit(false);
				for (Entry<String, Object[]> entry : entrySet) {
					pt=con.prepareStatement(entry.getKey());
					this.bind(entry.getValue());
					row[index] = pt.executeUpdate();
			
					index++;
				}
			}else{
				System.out.println("鏁版嵁搴撹繛鎺ュけ璐ワ紒");
			}
		} catch (JDBCException e) {
			System.out.println(e.getMessage());
			error++;
		}catch(Exception e){
			System.out.println(e.getMessage());
			error++;
		}
		finally{
			if(error>0){
				try {
					//鍙戠敓寮傚父锛屼簨鐗╁洖婊�
					con.rollback();
					System.out.println("rollback");
					
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}else{
				try {
					//娌℃湁寮傚父鍒欐墽琛屾彁浜や簨鐗�
					con.commit();
					
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			BaseDAO.closeAll(con, pt, null);
			
		}
		return row;
	}
	/**
	 * 
	 */
	private T tobean() {
		T t=null;
		try {
			t=c.newInstance();
			Field[] df = c.getDeclaredFields();
			for (Field field : df) {
				field.setAccessible(true);
				Object value=rt.getObject(field.getName());
				field.set(t, value);
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		return t;
	}
	/**
	 * 绑定参数：
	 */
	private void bind(Object[] obj) {
		try {
			if(obj!=null && obj.length>0){
				for (int i = 0; i < obj.length; i++) {
					pt.setObject(i+1, obj[i]);
				}
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 查询多个
	 * 
	 * @param sql
	 * @param filldata
	 * @param objects
	 * @return
	 * @throws ClassNotFoundException
	 * @throws SQLException
	 */

	public <T> List<T> excuteQuery(String sql, FillData<T> filldata, Object... objects)
			throws ClassNotFoundException, SQLException {
		con=BaseDAO.getConnections();
		pt = con.prepareStatement(sql);
		if (objects != null) {
			for (int i = 0; i < objects.length; i++) {
				pt.setObject(i + 1, objects[i]);
			}
		}
		ResultSet rs = pt.executeQuery();
		List<T> list = new ArrayList<T>();
		int cols = rs.getMetaData().getColumnCount();
		String[] str = new String[cols];
		for (int i = 0; i < str.length; i++) {
			str[i] = rs.getMetaData().getColumnName(i + 1);
		}
		while (rs.next()) {
			Map<String, Object> map = new HashMap<String, Object>();
			for (int i = 0; i < str.length; i++) {
				map.put(str[i], rs.getObject(str[i]));
			}
			list.add(filldata.fillData(map));
		}
		BaseDAO.closeAll(con, pt, null);
		return list;
	}

	<T> T excuteQueryOne(String sql, FillData<T> filldata, Object... objects)
			throws SQLException, ClassNotFoundException {
		// 调用连接
		con=BaseDAO.getConnections();
		// 创建执行对象
		pt = con.prepareStatement(sql);
		// 设置sql参数
		if (objects != null) {
			for (int i = 0; i < objects.length; i++) {
				pt.setObject(i + 1, objects[i]);
			}
		}

		// 执行sql语句,获取返回结果集
		ResultSet rs = pt.executeQuery();

		// 取rs的总列数
		int cols = rs.getMetaData().getColumnCount();
		// 将所有的列名保存起来
		String[] str = new String[cols];
		for (int i = 0; i < str.length; i++) {
			str[i] = rs.getMetaData().getColumnName(i + 1);
		}
		Map<String, Object> map = new HashMap<String, Object>();

		if (rs.next()) {
			// 读取rs中的每一条记录,
			// 读取每一列数据,存入到map
			for (int i = 0; i < str.length; i++) {
				map.put(str[i], rs.getObject(str[i]));
			}
		}
		BaseDAO.closeAll(con, pt, null);
		
		return filldata.fillData(map);
	}
}
